<template>
    <el-container class="course-editor">
        <el-container>
            <el-main style="background-color: white; position: relative">
                <span class="editor-title">蝌蚪课件编辑器
                    <el-button
                            class="course-save"
                            v-if="true || modified[activedEditor]"
                            type="success"
                            round
                            size="mini"
                            @click="courseSave"
                    >保存</el-button>
                </span>
                <el-tabs :value="activedEditor" @tab-click="tabEditor" :before-leave="previewBeforeLeave">
                    <el-tab-pane v-if="visibleTab('counter') && counter"
                                 label="柜台配置"
                                 name="counter"
                                 style="overflow: auto">
                        <span v-for="(item, i) in counter.items"
                              :key="`counter${i}_${item.name}`"
                              @click="itemClick(item)">
                            <el-tag
                                    class="item-tag"
                                    :type="activedItem && activedItem.name === item.name ? 'warning' : '' "
                                    :hit="activedItem && activedItem.name === item.name"
                            >{{item.name }}</el-tag>
                        </span>
                        <span @click="itemCreate">
                            <el-tag type="success" style="margin: 0 3px 3px 0">+ 添加物品</el-tag>
                        </span>
                        <course
                                key="course_edit"
                                :counter="counter"
                                :business="business"
                                :apps="apps"
                                mode="edit"
                        />
                    </el-tab-pane>
                    <el-tab-pane v-if="visibleTab('business') && business && business.scripts"
                                 label="业务脚本"
                                 name="business">
                        <el-row :gutter="24">
                            <el-col :span="6">
                                <el-tabs value="first">
                                    <el-tab-pane label="按业务环节" name="first">
                                        <span @click="clearFilter()">
                                            <el-tag
                                                    type="success"
                                                    style="cursor: pointer; display: block; margin: 3px 3px 10px 3px"
                                            >全部</el-tag>
                                        </span>
                                        <el-steps direction="vertical" :active="activeStep">
                                            <span
                                                    v-for="(step, i) in business.steps"
                                                    :key="step.title"
                                                    @click="scopeSelect(step, i)"
                                                    style="cursor:pointer;"
                                            >
                                                <el-step
                                                        :title="`${step.title} (业务环节: ${step.pages})`"
                                                        :description="step.description"
                                                ></el-step>
                                            </span>
                                        </el-steps>
                                    </el-tab-pane>
                                    <el-tab-pane label="按物品" name="second">
                                        <span @click="clearFilter()">
                                            <el-tag type="success"
                                                    style="cursor: pointer; display: block; margin: 3px"
                                            >全部</el-tag>
                                        </span>
                                        <span v-for="(item, i) in scriptItems"
                                              :key="`business${i}` + item.name"
                                              @click="nameSelect(item)"
                                        >
                                            <el-tag style="display: block; margin: 3px"
                                                    :type="filter && filter.itemName === item.name ? 'warning' : '' "
                                                    :hit="filter && filter.itemName === item.name"
                                            >{{ item.name }}</el-tag>
                                        </span>
                                    </el-tab-pane>
                                </el-tabs>
                            </el-col>
                            <el-col :span="18">
                                <span @click="itemCreate">
                                    <el-tag type="success" class="tag-btn tag-item">+ 新增环节</el-tag>
                                </span>
                                <span @click="itemUp" v-if="canMove">
                                    <el-tag type="primary" class="tag-btn tag-item">↑ 向上移动</el-tag>
                                </span>
                                <span @click="itemDown" v-if="canMove">
                                    <el-tag type="primary" class="tag-btn tag-item">↓ 向下移动</el-tag>
                                </span>
                                <el-table :data="validItems"
                                          stripe
                                          style="width: 100%"
                                          highlight-current-row
                                          @current-change="rowSelect">
                                    <el-table-column prop="scope" label="环节范围" />
                                    <el-table-column prop="name" label="物品名称" />
                                    <el-table-column prop="type"
                                                     label="类别"
                                                     width="100px"
                                                     :formatter="stepLabelFormatter" />
                                    <el-table-column prop="stepScore"
                                                     label="环节得分">
                                        <template slot-scope="scope">
                                            <div v-html="stepScoreFormatter(scope.row)" />
                                        </template>
                                    </el-table-column>
                                    <el-table-column label="内容">
                                        <template slot-scope="scope">
                                            {{ typeof scope.row.content === 'object' ?
                                            JSON.stringify(scope.row.content) :
                                            scope.row.content }}
                                        </template>
                                    </el-table-column>
                                </el-table>
                            </el-col>
                        </el-row>
                    </el-tab-pane>
                    <el-tab-pane v-if="visibleTab('apps')" label="交易系统" name="apps">
                        <el-tabs tab-position="left"
                                 style="height: 100%"
                                 :value="activedApp"
                                 @tab-click="tabApp">
                            <el-tab-pane v-for="app in apps"
                                         :key="'app' + app.name"
                                         :label="app.name"
                                         :name="app.name"
                                         style="overflow: auto">
                                <span v-for="(item, i) in app.items"
                                      :key="`app${i}_${item.name}`"
                                      @click="itemClick(item)">
                                    <el-tag
                                            class="item-tag"
                                            :type="activedItem && activedItem.name === item.name ? 'warning' : '' "
                                            :hit="activedItem && activedItem.name === item.name"
                                    >{{item.name }}</el-tag>
                                </span>
                                <span @click="itemCreate">
                                    <el-tag type="success" style="margin: 0 3px 3px 0">+ 添加组件</el-tag>
                                </span>
                                <span @click="() => itemToPrev(app.items)">
                                    <el-tag type="success" style="margin: 0 3px 3px 0">前移</el-tag>
                                </span>
                                <span @click="() => itemToNext(app.items)">
                                    <el-tag type="success" style="margin: 0 3px 3px 0">后移</el-tag>
                                </span>

                                <app-item :item="{ title: app.name, content: app.name}"
                                          :counter="counter"
                                          :apps="apps"
                                          mode="edit"
                                />
                            </el-tab-pane>
                            <el-tab-pane label=" + 添加交易界面" name="add" />
                        </el-tabs>
                    </el-tab-pane>
                    <el-tab-pane label="预览" name="preview" v-if="editor != 'counter'">
                        <course key="course_preview"
                                ref="coursePreview"
                                :counter="counter"
                                :business="business"
                                :apps="previewApps"
                                :mode="preview"
                                :action="'edit_preview'"
                        />
                    </el-tab-pane>
                </el-tabs>
            </el-main>
        </el-container>
        <el-aside width="300px">
            <el-main style="background-color: white">
                <el-tabs class="config-form" :value="activedConfig" @tab-click="tabConfig">
                    <el-tab-pane v-if="activedEditor === 'counter'" label="柜台属性" name="counter">
                        <counter-config />
                    </el-tab-pane>
                    <el-tab-pane v-if="activedEditor === 'business'" label="业务属性" name="business">
                        <business-config :business="business" :counters="counters" />
                    </el-tab-pane>
                    <el-tab-pane v-if="activedEditor === 'apps'" label="交易属性" name="apps">
                        <app-config />
                    </el-tab-pane>
                    <el-tab-pane v-if="activedEditor !== 'preview'" label="物品属性" name="item">
                        <item-config />
                    </el-tab-pane>
                    <el-tab-pane v-if="activedEditor === 'preview'" label="状态监控" name="preview">
                        <el-form label-position="left" size="mini" label-width="80px">
                            <el-form-item label="当前环节">
                                <el-input-number v-model="$refs.coursePreview.pages" @change="setCurrentPage" />
                            </el-form-item>
                            <el-form-item label="指定步骤">
                                <span slot="label" style="color: red">*指定步骤</span>
                                <el-select @change="setStepPage($event, $refs.coursePreview.pages)"
                                           value="">
                                    <el-option v-for="(step, i) in business.steps"
                                               :key="i"
                                               :label="`${i + 1} - ${step.title}`"
                                               :value="i" />
                                </el-select>
                            </el-form-item>
                        </el-form>
                        <el-collapse v-if="business"
                                     v-model="activeStep"
                                     accordion
                                     @change="$refs.coursePreview.pagesGoto($event.pages)">
                            <el-collapse-item
                                    v-for="(step, i) in business.steps"
                                    :key="step.title + step.pages"
                                    :name="step.title">
                                <div slot="title"
                                     style="display: flex; justify-content: space-between">
                                    <div>{{ `${i+1}. ${step.title}` }}</div>
                                    <div>{{ `业务环节: ${step.pages}` }}</div>
                                </div>
                                <ul>
                                    <li v-for="item in getItemsByStepIndex(i)" :key="item.uid">
                                        <span style="float: left">{{ item.name }}</span>
                                        <span
                                                style="float: right"
                                        >{{ item.display ? '显示' : '隐藏' }}</span>
                                    </li>
                                    <ul></ul>
                                </ul>
                            </el-collapse-item>
                        </el-collapse>
                    </el-tab-pane>
                </el-tabs>
            </el-main>
        </el-aside>
    </el-container>
</template>
<script>
    import Vue from 'vue'
    import { mapGetters, mapState } from 'vuex'
    import { Message } from 'element-ui'
    import cloneDeep from 'lodash/cloneDeep'

    import course from './course'
    import business from './data/business'
    import apps from './data/apps'
    import floatItem from './components/floatItem'
    import appItem from './components/appItem'
    import counterConfig from './components/counterConfig'
    import itemConfig from './components/itemConfig'
    import businessConfig from './components/businessConfig'
    import appConfig from './components/appConfig'
    import { itemTypes } from './data/consts'

    export default {
        name: 'course-editor',
        components: {
            course,
            'float-item': floatItem,
            'app-item': appItem,
            'counter-config': counterConfig,
            'item-config': itemConfig,
            'business-config': businessConfig,
            'app-config': appConfig
        },
        data() {
            return {
                preview: 'study',
                businessId: null,
                counterId: null,
                appTemplateId: null,
                activeStep: null,
                editor: null,
                filter: {
                    itemName: null,
                    nextScope: null,
                    currScope: null
                }
            }
        },
        computed: {
            ...mapGetters('course', ['modified']),
            ...mapState('course', [
                'activedEditor',
                'activedConfig',
                'activedItem',
                'activedApp',
                'apps',
                'previewApps',
                'business',
                'counter',
                'counters'
            ]),
            validItems() {
                const scripts = this.business.scripts || []
                const { itemName, nextScope, currScope } = this.filter
                if (!currScope && currScope !== 0 && !itemName) {
                    return scripts
                }
                let itemsByScope = []
                for (const item of scripts) {
                    if (itemName !== null && item.name === itemName) {
                        itemsByScope.push(item)
                    } else if (currScope !== null && this.validItemByScope(item.scope, currScope, nextScope)) {
                        itemsByScope.push(item)
                    }
                }
                return itemsByScope
            },
            scriptItems() {
                return this.business.scripts.reduce((last, curr) => {
                    const exist = last.find(item => item.name === curr.name)
                    if (!exist) {
                        last.push(curr)
                    }
                    return last
                }, [])
            },
            canMove() {
                const { currScope } = this.filter
                return (
                    !currScope &&
                    currScope !== 0 &&
                    this.validItems &&
                    this.business.scripts &&
                    this.validItems.length === this.business.scripts.length
                )
            }
        },
        created() {
            // 根据参数id，初始化business对象
            const { commit, dispatch } = this.$store
            this.counterId = this.$route.query.counterId
            this.businessId = this.$route.query.businessId
            this.appTemplateId = this.$route.query.appTemplateId
            let editor = 'business'
            if (this.counterId) {
                dispatch('course/getCounterById', this.counterId)
                this.editor = editor = 'counter'
            } else if (this.businessId) {
                dispatch('course/getCounters')
                dispatch('course/getBusinessById', this.businessId)
                this.editor = editor = 'business'
            }
            commit('course/update', { activedEditor: editor })
            commit('course/update', { activedConfig: editor })
        },
        mounted() {
            const { commit } = this.$store
            if (!this.businessId && !this.counterId) {
                commit('course/update', { counter: business[1].counter })
            }
            if (!this.businessId) {
                commit('course/update', { business: business[1] })
            }
            if (!this.businessId && !this.appTemplateId) {
                commit('course/update', { apps })
            }
            commit('course/cache')
        },
        methods: {
            previewBeforeLeave(activeView, oldActiveView) {
                if ('preview' == activeView) {
                    this.$store.commit('course/setPreviewApps', cloneDeep(this.apps))
                }
            },
            courseSave() {
                console.log('courseSave', this.business)
                const { dispatch } = this.$store
                if (this.editor === 'counter') {
                    dispatch('course/saveCounter', this.counter)
                } else {
                    dispatch('course/saveBusinessTemplate')
                }
            },
            visibleTab(editor) {
                return (
                    this.activedEditor === editor ||
                    this.businessId ||
                    (!this.businessId && !this.counterId && !this.appTemplateId)
                )
            },
            stepLabelFormatter(row, col) {
                const itemType = itemTypes.find(type => type.value === row[col.property])
                return itemType ? itemType.label : ''
            },
            stepScoreFormatter(row) {
                let scoreResult = null
                if (row.onChange && row.onChange.pages > 0 && row.onChange.score > 0) {
                    scoreResult = { event: '结果验证', score: row.onChange.score }
                }
                if (row.onDrag && row.onDrag.pages > 0 && row.onDrag.score > 0) {
                    scoreResult = { event: '拖拽', score: row.onDrag.score }
                }
                if (row.onClick && row.onClick.pages > 0 && row.onClick.score) {
                    scoreResult = { event: '点击', score: row.onClick.score }
                }
                return scoreResult ? `<ul>
                                    <li>事件：${scoreResult.event}</li>
                                    <li>得分：${scoreResult.score}</li>
                                  </ul>` : ''
            },
            validItemByScope(scopes, min, max) {
                // console.log('validItemByScope', 'scopes=', scopes, 'min=', min, 'max=', max)
                min = min === null ? 0 : min
                const groups = scopes.split(',')
                let valid = false
                groups.forEach(group => {
                    if (!Number.isNaN(group) && group >= min && (group < max || null === max)) {
                        valid = true
                    }
                    if (group.indexOf('-') > -1) {
                        const [start, end] = group.split('-').map(num => Number(num))
                        if (end >= min && start < max) {
                            valid = true
                        }
                    }
                    if (group.indexOf('+') > -1) {
                        const pos = group.indexOf('+')
                        const num = Number(group.replace('+', ''))
                        if (pos === 0) {
                            if (num >= min) {
                                valid = true
                            }
                        } else {
                            if (num < max || null === max) {
                                valid = true
                            }
                        }
                    }
                })
                return valid
            },
            itemCreate() {
                const { commit } = this.$store
                commit('course/update', { activedConfig: 'item' })
                commit('course/addActivedItem', {
                    name: '',
                    type: '',
                    scope: '0+',
                    display: true,
                    w: 100,
                    h: 100,
                    x: 10,
                    y: 10,
                    icon: '',
                    content: '',
                    onClick: {}
                })
            },
            itemToPrev(items) {
                let index = -1
                for (let i = 0; i < items.length; ++i) {
                    if (items[i].uid == this.activedItem.uid) {
                        index = i
                        break;
                    }
                }
                if (index <= 0) {
                    return
                }

                Vue.set(items, index, items[index - 1])
                Vue.set(items, index - 1, this.activedItem)
            },
            itemToNext(items) {
                let index = -1
                for (let i = 0; i < items.length; ++i) {
                    if (items[i].uid == this.activedItem.uid) {
                        index = i
                        break;
                    }
                }
                if (index >= items.length - 1) {
                    return
                }

                Vue.set(items, index, items[index + 1])
                Vue.set(items, index + 1, this.activedItem)
            },
            itemUp() {
                if (!this.business || !this.business.scripts) return
                const { uid } = this.activedItem
                let index = 0
                for (const script of this.business.scripts) {
                    if (script.uid === uid) break
                    ++index
                }
                if (index - 1 < 0) return
                Vue.set(this.business.scripts, index, this.business.scripts[index - 1])
                Vue.set(this.business.scripts, index - 1, this.activedItem)
            },
            itemDown() {
                if (!this.business || !this.business.scripts) return
                const { uid } = this.activedItem
                let index = 0
                for (const script of this.business.scripts) {
                    if (script.uid === uid) break
                    ++index
                }
                if (index + 1 >= this.business.scripts.length) return
                Vue.set(this.business.scripts, index, this.business.scripts[index + 1])
                Vue.set(this.business.scripts, index + 1, this.activedItem)
            },
            itemClick(item) {
                const { commit } = this.$store
                commit('course/update', { activedItem: item })
                commit('course/update', { activedConfig: 'item' })
            },
            tabEditor(tab) {
                const { commit } = this.$store
                commit('course/update', { activedEditor: tab.name })
                commit('course/update', { activedConfig: tab.name })
                commit('course/update', { activedItem: null })
                // 强制刷新布局
                window.dispatchEvent(new Event('resize'))
            },
            tabApp(tab) {
                const { commit } = this.$store
                if (tab.name === 'add') {
                    const app = {
                        name: '新的交易页面',
                        background: '',
                        items: [],
                        events: {},
                        tips: ''
                    }
                    commit('course/addActivedApp', app)
                    commit('course/update', { activedApp: app.name })
                } else {
                    commit('course/update', { activedApp: tab.name })
                }
                commit('course/update', { activedConfig: 'apps' })
                commit('course/update', { activedItem: null })
            },
            tabConfig(tab) {
                this.$store.commit('course/update', { activedConfig: tab.name })
            },
            rowSelect(item) {
                // this.itemName = item.name;
                this.itemClick(item)
            },
            nameSelect(item) {
                this.filter.itemName = item.name
                this.filter.currScope = null
                this.filter.nextScope = null
            },
            scopeSelect(step, i) {
                this.filter.itemName = null
                this.filter.currScope = step.pages
                this.filter.nextScope = this.business.steps[i + 1] ? this.business.steps[i + 1].pages : null
                Vue.set(this, 'activeStep', i)
            },
            clearFilter() {
                this.filter = {
                    itemName: null,
                    nextScope: null,
                    currScope: null
                }
                this.activeStep = null
            },
            setStepPage(index, pages) {
                const step = this.business.steps[index]
                this.activeStep = step
                step.pages = pages
                this.$store.commit('courese/setBusinessStep', { index, step })
                Message({
                    message: `业务步骤 - ${step.title} 的初始已设置为从业务环节 ${pages} 开始`,
                    type: 'success'
                })
            },
            setCurrentPage(page) {
                this.$refs.coursePreview.pagesGoto(page)
            },
            getItemsByStepIndex(index) {
                const scripts = this.business.scripts || []
                const currStep = this.business.steps[index]
                const nextStep = this.business.steps[index + 1] || this.business.steps[index]
                const itemsByScope = scripts.filter(item =>
                    this.validItemByScope(item.scope, currStep.pages, nextStep.pages)
                )
                return itemsByScope
            }
        }
    }
</script>
<style lang="less">
    .course-editor {
        .course-save {
            margin-bottom: 10px;
            margin-left: 15px;
        }

        .tag-btn {
            cursor: pointer;
        }
    }

    .item-tag {
        margin: 0 3px 3px 0;
    }

    .same-item {
        border-color: #409eff;
        background-color: rgba(230, 162, 60, 0.1);
        font-size: 120%;
        font-weight: 700;
        color: #409eff;
    }

    .config-form {
        .el-tab-pane {
            height: 85vh;
            overflow-y: scroll;
        }
    }

    .editor-title {
        z-index: 10;
        display: flex;
        position: absolute;
        right: 50px;
        font-size: 24px;
        color: #6b708f;
    }

    .step-btn {
        cursor: pointer;
        display: block;
        margin: 10px 3px 3px 3px;
    }
</style>

